package net.gazhi.delonix.core.service;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;

/**
 * 实体业务逻辑 Service 基类
 * 
 * @author Jeffrey Lin
 * 
 * @param <T>
 */
public abstract class AbstractEntityService<T> extends AbstractService {

	/**
	 * 泛型实体的确定类
	 */
	private Class<?> entityClass;

	public AbstractEntityService() {
		// 在构建时，取得泛型对应的实体类
		Type genType = getClass().getGenericSuperclass();
		if (genType instanceof ParameterizedType) {
			Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
			entityClass = (Class<?>) params[0];
		}
	}

	public Class<?> getEntityClass() {
		return entityClass;
	}

	@SuppressWarnings("unchecked")
	public T get(Serializable id) {
		return (T) dao.get(entityClass, id);
	}

	protected Criteria createCriteria() {
		return createCriteria(entityClass);
	}

	protected Criteria createCriteria(String alias) {
		return createCriteria(entityClass, alias);
	}

	/**
	 * 判断是否存在指定属性值的实体
	 * 
	 * @param propertyName
	 * @param value
	 * @return
	 */
	public boolean existed(String propertyName, Object value) {
		return this.otherExisted(null, propertyName, value);
	}

	/**
	 * 判断是否存在指定的 <u>多个</u> 属性值的实体
	 * 
	 * @param propertyMap
	 * @return
	 */
	public boolean existed(Map<String, Object> propertyMap) {
		return this.otherExisted(null, propertyMap);
	}

	/**
	 * 判断是否存在指定属性值的 <u>其他</u> 实体
	 * 
	 * @param neId
	 * @param propertyName
	 * @param value
	 * @return
	 */
	public boolean otherExisted(Serializable neId, String propertyName, Object value) {
		Map<String, Object> propertyMap = new HashMap<String, Object>();
		propertyMap.put(propertyName, value);
		return this.otherExisted(neId, propertyMap);
	}

	/**
	 * 判断是否存在 指定的 <u>多个</u> 属性值的 <u>其他</u> 实体
	 * 
	 * @param neId
	 * @param propertyMap
	 * @return
	 */
	public boolean otherExisted(Serializable neId, Map<String, Object> propertyMap) {
		Criteria query = dao.createCriteria(entityClass);
		if (neId != null) {
			query.add(Restrictions.ne("id", neId));
		}
		for (Map.Entry<String, Object> entry : propertyMap.entrySet()) {
			if (entry.getValue() == null) {
				query.add(Restrictions.isNull(entry.getKey()));
			} else {
				query.add(Restrictions.eq(entry.getKey(), entry.getValue()));
			}
		}
		return query.setMaxResults(1).uniqueResult() != null;
	}

}
